Vox A performant static site generator built to scale.

⟵ Diary

Layout Inheritance, User Guide

Notes

This site is used to debug changes to Vox. First, the global.url of the site is changed, then this command is used to rebuild & serve:

clear; rm -rf ./output; ./prebuild.sh; vox serve -d -s -w -vv

Goals

Today’s agenda:

  • Parallelising both rendering and writing to disk.
  • Implementing partial date-times.
  • Redesigning layout inheritance.
    • In layout inheritance, the lowest layout should include chained parent contexts up to the first non-layout page.
  • Fixing the {% markdown %} block.
  • Finishing the user guide.
  • Modifying code according to lints.
  • Improving syntax highlighting.

Parallelisation

Rendering

Two areas of the code would need modification:

  • The fifth step in the watching rendering pipeline
  • The initial build

In both, topological sorting is performed to determine the rendering order of pages. After the rendering order is determined, pages are rendered sequentially. Simply rendering in parallel is not valid for two reasons:

  • The order pages are rendered in matters
  • Rendering a page involves mutating data shared across page renders

When a page is rendered, its parents are sequentially iterated upon to:

  • Determine if the page being rendered is a layout (determining the layout and page contexts)
  • Note the collection pages that the page being rendered is a dependent of Afterwards, the noted collection pages are sequentially iterated upon to build the contexts for each collection.

These two sequential iterations cannot instead be performed in parallel either, as they involve mutating shared data.

Therefore, it is not possible to parallelise the rendering process.

Writing

Two areas of the code would need modification:

  • The fifth step in the watching rendering pipeline
  • The initial build

In both, a list of rendered pages is sequentially iterated upon to write them to disk.

These two sequential iterations cannot instead be performed in parallel, as the order in which pages are written matters.

Partial Date-Times

It seems this was already implemented and simply forgotten.

Layout Inheritance

Currently, when a page is rendered, the layout context is created to represent the current page, when the current page being rendered is a layout. Then, the direct parent page of which the current page is a layout for is assigned the page context. The consequence of this is that a non-layout page can only pass its context to its immediate layout child.

To enable the passage of all contexts:

  1. The ancestors of a layout up to (and including) the first non-layout page should be found.
  2. Define the contexts:
    • The layout itself should be labelled with the layout context.
    • The layout’s ancestors (in ascending order) should define a layouts context.
    • The non-layout ancestor is additionally given the page context.

Markdown

Currently, Markdown is rendered, then the output is sent to the Liquid renderer. This introduces issues where text gets cobbled, and it requires turning off smart quotes so the Markdown rendering doesn’t break the templating. To fix this, the block should render all of the templating inside, then render the Markdown.

User Guide

Currently, the page on the data model is out-of-date. It needs to be updated to reflect the addition of layout inheritance. It is also incomplete, lacking sections on each of the templating contexts. When pagination is implemented, the data model article should be updated.

Lints

Two code patterns were found in the code: manual_flatten and assigning_clones.

manual_flatten

Before
for entry in snippets_directory {
    if let Ok(entry) = entry {
        if entry.file_type().unwrap().is_file() {
            let name = entry
                .path()
                .file_name()
                .unwrap()
                .to_string_lossy()
                .to_string();
            self.names.push(name);
        }
    }
}
After
for entry in snippets_directory.flatten() {
    if entry.file_type().unwrap().is_file() {
        let name = entry
            .path()
            .file_name()
            .unwrap()
            .to_string_lossy()
            .to_string();
        self.names.push(name);
    }
}

assigning_clones

Before
new_page.url = old_page.url.clone();
new_page.rendered = old_page.rendered.clone();
After
new_page.url.clone_from(&old_page.url);
new_page.rendered.clone_from(&old_page.rendered);

Syntax Highlighting

Currently, syntax highlighting is performed by colouring the HTML output. This has the drawback of making the highlighting impossible to style (eg, with separate light and dark stylesheets).

To improve this, syntax highlighting should use CSS classes, with an additional CLI flag to generate a stylesheet for syntax highlighting.


Future Goals

  • Implementing pagination.
    • If a page’s frontmatter has the paginate key (an integer), create in-memory copies of the page, each with different pagination values, ranging from 0 up to (but not including) the value of paginate.
  • Documenting the CLI code.
  • Creating a logo for Vox.
  • Upgrading all direct dependencies.
  • Modify log output to be more helpful for end-users.
  • Removing code that was commented out.